package cn.harry.modular.sys.controller;

import cn.harry.common.api.R;
import cn.harry.common.utils.*;
import cn.harry.modular.sys.domain.SysUser;
import cn.harry.modular.sys.enums.ConfigEnums;
import cn.harry.modular.sys.param.SysUserLoginParam;
import cn.harry.modular.sys.service.SysCaptchaService;
import cn.harry.modular.sys.service.SysUserService;
import cn.harry.modular.sys.utils.ParamResolver;
import cn.harry.modular.sys.vo.CaptchaResult;
import cn.harry.modular.sys.vo.LoginResult;
import cn.harry.modular.sys.vo.SysUserInfo;
import cn.harry.modular.sys.vo.UserInfoResult;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import io.springboot.captcha.ArithmeticCaptcha;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

/**
 * ClassName: SysLoginController Description:
 *
 * @author honghh Date 2019/10/15 12:42 Copyright (C) www.tech-harry.cn
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@Tag(name = "admin 认证中心")
@RequestMapping("/admin")
public class SysLoginController {

    private final SysCaptchaService sysCaptchaService;

    private final SysUserService sysUserService;

    private final JwtTokenUtil jwtTokenUtil;

    @Operation(summary = "login 登录以后返回token")
    @PostMapping(value = "/login")
    public R<LoginResult> login(@RequestBody SysUserLoginParam sysUserLoginParam) {
        // 获取系统验证码开关
        boolean sw = Boolean.parseBoolean(ParamResolver.getStr(ConfigEnums.SYS_CAPTCHA_IMG.name(), "true"));
        if (sw) {
            // 验证码校验
            boolean captcha = sysCaptchaService.validate(sysUserLoginParam.getUuid(),
                    sysUserLoginParam.getCode());
            if (!captcha) {
                return R.failed("验证码不正确");
            }
        }
        return R.success(sysUserService.login(sysUserLoginParam.getUsername(),
                sysUserLoginParam.getPassword()));
    }

    @Operation(summary = "token/refresh 刷新token")
    @GetMapping(value = "/token/refresh")
    public R<LoginResult> refreshToken(HttpServletRequest request) {
        String token = request.getHeader(jwtTokenUtil.getTokenHeader());
        if (StrUtil.isBlank(token)) {
            log.error("token 为空");
            return R.failed();
        }
        String refreshToken = sysUserService.refreshToken(token);
        if (StrUtil.isBlank(refreshToken)) {
            log.error("refreshToken 无效");
            return R.failed();
        }
        return R.success(new LoginResult(refreshToken, jwtTokenUtil.getTokenHead(),
                jwtTokenUtil.getExpiration()));
    }

    @Operation(summary = "info 获取当前登录用户信息")
    @GetMapping(value = "/info")
    public R<UserInfoResult> getInfo() {
        SysUserDetails sysUserDetails = SecurityUtils.getSysUserDetails();
        SysUser user = sysUserDetails.getSysUser();
        return R.success(new UserInfoResult(user.getUsername(), sysUserDetails.getRoles(),
                sysUserDetails.getPermissions(),
                BeanUtils.transform(SysUserInfo.class, user)));
    }

    @Operation(summary = "logout 登出功能")
    @PostMapping(value = "/logout")
    public R logout(HttpServletRequest request) {
        SecurityContextHolder.clearContext();
        return R.success();
    }

    /**
     * 生成验证码
     */
    @Operation(summary = "captcha 生成验证码")
    @GetMapping("captcha")
    public R<CaptchaResult> captcha() {
        // 三个参数分别为宽、高、位数
        ArithmeticCaptcha specCaptcha = new ArithmeticCaptcha(130, 48);
        // 唯一标识
        String uuid = IdUtil.simpleUUID();
        // 获取当前的验证码
        String code = specCaptcha.text().toLowerCase();
        // 将验证码存到redis中 并设置5分钟过期
        RedisUtils.set(RedisKeys.getCaptchaKey(uuid), code, 5 * 60);

        // 验证码开关
        boolean sw = Boolean.parseBoolean(ParamResolver.getStr(ConfigEnums.SYS_CAPTCHA_IMG.name(), "true"));
        return R.success(new CaptchaResult(uuid, specCaptcha.toBase64(), sw));
    }

}
